//===============================================================================
// Microsoft Architecture Strategy Team
// LitwareHR - SaaS Sample Application
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================


namespace Shp.Runtime.DataModel.Sitka
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using Shp.Runtime.Common;
    using Shp.Runtime.Contract;
    using Shp.Runtime.DataModel.Sitka.Constants;
    using Shp.Runtime.Sitka.ServiceAgent;
    using Shp.Runtime.Sitka.ServiceAgent.Entities;

    public class WorkflowDataModel
    {
        private const string WorkflowEntityDefName = "WorkflowDef";

        private const string WorkflowEntityRuleSetDefName = "RuleSetDef";
        private const string WorkflowNameRuleSet = "Markup";

        private const string WorkflowNameField = "Name";
        private const string WorkflowXomlField = "Xoml";
        private const string TenantIdNameField = "TenantId";

        private IRepositoryFactory repositoryFactory;

        public WorkflowDataModel(IRepositoryFactory factory)
        {
            repositoryFactory = factory;
        }

        public WorkflowDataModel()
        {
            repositoryFactory = new GenericRepositoryFactory();
        }

        public Guid AddWorkflowDef(Guid tenantId, string name, string xoml)
        {
            Guid workflowDefId = Guid.NewGuid();

            using (Repository<GenericExtensibleEntity> repository = repositoryFactory.MetadataRepository)
            {
                GenericExtensibleEntity extensibleEntity = new GenericExtensibleEntity(WorkflowEntityDefName, workflowDefId);

                extensibleEntity.Fields.Add(new Field(TenantIdNameField, tenantId.ToString()));
                extensibleEntity.Fields.Add(new Field(WorkflowNameField, name));
                extensibleEntity.Fields.Add(new Field(WorkflowXomlField, xoml));

                repository.Insert(extensibleEntity);
            }

            return workflowDefId;
        }

        public void UpdateWorkflowDef(Guid tenantId, Guid workflowId, string name, string xoml)
        {
            using (Repository<GenericExtensibleEntity> repository = repositoryFactory.MetadataRepository)
            {
                GenericExtensibleEntity extensibleEntity = new GenericExtensibleEntity(WorkflowEntityDefName, workflowId);

                extensibleEntity.Fields.Add(new Field(TenantIdNameField, tenantId.ToString()));
                extensibleEntity.Fields.Add(new Field(WorkflowNameField, name));
                extensibleEntity.Fields.Add(new Field(WorkflowXomlField, xoml));

                //updated workflowDef
                repository.Update(extensibleEntity);
            }
        }

        public WorkflowDto GetWorkflowDef(Guid workflowDefId)
        {
            WorkflowDto workflowDef;

            using (Repository<GenericExtensibleEntity> repository = repositoryFactory.MetadataRepository)
            {
                GenericExtensibleEntity extensibleEntity = repository.GetById(workflowDefId);

                workflowDef = new WorkflowDto();
                workflowDef.Id = workflowDefId;
                workflowDef.Name = extensibleEntity.GetFieldValue(WorkflowNameField);
                workflowDef.Xoml = extensibleEntity.GetFieldValue(WorkflowXomlField);

                return workflowDef;
            }

            throw new ArgumentException("workflowDefId");
        }

        public void DeleteWorkflowDef(Guid workflowId)
        {
            try
            {
                using (Repository<GenericExtensibleEntity> repository = repositoryFactory.MetadataRepository)
                {
                    repository.Delete(workflowId);
                }
            }
            catch
            { throw; }
        }

        public Dictionary<Guid, string> GetWorkflowDefList(Guid tenantId)
        {
            Dictionary<Guid, string> list = new Dictionary<Guid, string>();

            using (Repository<GenericExtensibleEntity> repository = repositoryFactory.MetadataRepository)
            {
                IEnumerable<GenericExtensibleEntity> listExtensibleEntities = repository.Search(string.Format(CultureInfo.InvariantCulture, Constants.SitkaMetadataQueries.GetEntityDefByTenant, WorkflowEntityDefName, tenantId.ToString()));

                foreach (GenericExtensibleEntity item in listExtensibleEntities)
                {
                    list.Add(item.Id, item.GetFieldValue(WorkflowNameField));
                }
            }

            return list;
        }

        public void UpdateRuleSetDef(Guid tenantId, string markup)
        {
            Guid workflowRuleSetId = Guid.NewGuid();

            using (Repository<GenericExtensibleEntity> repository = repositoryFactory.MetadataRepository)
            {
                IEnumerable<GenericExtensibleEntity> list = repository.Search(string.Format(CultureInfo.InvariantCulture, SitkaMetadataQueries.GetEntityDefByTenant, WorkflowEntityRuleSetDefName, tenantId.ToString()));
                if (list != null && list.Count() > 0)
                {
                    GenericExtensibleEntity ruleSetEntity = list.First();
                    ruleSetEntity.Fields.Clear();
                    ruleSetEntity.Fields.Add(new Field(TenantIdNameField, tenantId.ToString()));
                    ruleSetEntity.Fields.Add(new Field(WorkflowNameRuleSet, markup));

                    repository.Update(ruleSetEntity);
                }
                else
                {
                    GenericExtensibleEntity ruleSetEntity = new GenericExtensibleEntity(WorkflowEntityRuleSetDefName, workflowRuleSetId);
                    ruleSetEntity.Fields.Add(new Field(WorkflowNameRuleSet, markup));
                    ruleSetEntity.Fields.Add(new Field(TenantIdNameField, tenantId.ToString()));

                    repository.Insert(ruleSetEntity);
                }
            }
        }

        public string GetRuleSetDef(Guid tenantId)
        {
            using (Repository<GenericExtensibleEntity> repository = repositoryFactory.MetadataRepository)
            {
                string result = string.Empty;
                IEnumerable<GenericExtensibleEntity> list = repository.Search(string.Format(CultureInfo.InvariantCulture, SitkaMetadataQueries.GetEntityDefByTenant, WorkflowEntityRuleSetDefName, tenantId.ToString()));
                if (list != null)
                {
                    GenericExtensibleEntity ruleSetEntity = list.First();
                    result = ruleSetEntity.GetFieldValue(WorkflowNameRuleSet);
                }

                return result;
            }
        }
    }
}

